package utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import model.file.FileUsers;
import view.Client;

import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class AsyncFileIOUtil {

    private static String filePath;
    private static String fileName;

    /*
    * 设置文件地址信息
    * */
    private static void setFileInfo(String path, String name) {
        filePath = path;
        fileName = name;
    }

    /*
    * 总行数转化等差数列
    * */
    private static List<Long> averageNumberArr(long totalLine){
        List<Long> l = new ArrayList<>();
        int parts = 40;
        // 计算每份的平均值
        double average = (double) totalLine / parts;

        // 输出每份的值
        for (int i = 0; i <= parts; i++) {
            long partValue = Math.round(average);
            totalLine -= partValue;
            if (totalLine >= 0){
                l.add(totalLine);
//                System.out.println(totalLine);
            }
        }
        return l;
    }


    /*
    * 获取文件总行数
    * */
    private static List<Long> fileTotalLine(){
        long lineNumber = -1;
        try (LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(filePath+fileName))){
            lineNumberReader.skip(Long.MAX_VALUE);
            lineNumber = lineNumberReader.getLineNumber();
            lineNumberReader.close();
            return averageNumberArr(lineNumber-1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /*
    * 文件读取
    * */
    public static Thread fileRead(String path, String name,String tableName) {
        setFileInfo(path, name);
        AsyncFileRead asyncFileRead = new AsyncFileRead(tableName,fileTotalLine(),path+name);
        Thread t = new Thread(asyncFileRead);
        t.start();
        return t;

    }

    static class AsyncFileWrite implements Runnable {
        List<String> lines;
        String tableName;

        public AsyncFileWrite(List<String> lines,String t) {
            this.lines = lines;
            this.tableName = t;
        }

        @Override
        public void run() {
            fileWrite(lines,tableName);
        }

        /*
         * 向数据库写入*/
        private void fileWrite(List<String> ss,String tableName) {
            String url = "jdbc:mysql://127.0.0.1:3306/shopping?useUnicode=true&characterEncoding=GBK&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowMultiQueries=true";
            try (Connection connection = DriverManager.getConnection(url, "root", "root");PreparedStatement pst = connection.prepareStatement(url);) {
                for (String item : ss) {
                    if (item.contains("["))
                        item = item.replace("[", "");
                    if (item.contains("]"))
                        item = item.replace("]", "");
                    String sql = sqlInsert(JSON.parseObject(item), tableName);
                    pst.addBatch(sql);
                }
                pst.executeBatch();
            } catch (SQLException e) {
//                e.printStackTrace();
            }

        }

        /*
        * json转sql语句
        * */
        private String sqlInsert(JSONObject lineJson, String tableName) {

            //先转成 insert into tableName (若干字段) 形式
            StringBuilder sb = new StringBuilder("INSERT INTO ")
                    .append(tableName)
                    .append(" (");

            for (String key : lineJson.keySet()) {
                if ("deleteField".equals(key)) {
                    continue;
                }
                sb.append(key).append(",");
            }
            sb.deleteCharAt(sb.length() - 1);

            // 转成 VALUES("内容"); 形式
            sb.append(") VALUES ( ");
            for (String key : lineJson.keySet()) {
                if ("deleteField".equals(key)) {
                    continue;
                }
                sb.append("\"")
                        .append(lineJson.getString(key))
                        .append("\"");

                sb.append(",");
            }
            sb.deleteCharAt(sb.length() - 1);
            sb.append(")").append(";");
            return  sb.toString();
        }

    }

    /*
     * 读取json文件
     * 因为是子线程,主线程不会等待子线程执行完再关闭,所以测试类中看不到打印结果"有时"
     * 单个子线程读取，多线程写
     * */
    static class AsyncFileRead implements Runnable {
        private String tableName;
        private List<Long> lines;
        private String totalPath;
        List<Thread> threadList = new ArrayList<>();

        public AsyncFileRead(String tableName, List<Long> l,String p) {
            this.tableName = tableName;
            this.lines = l;
            this.totalPath = p;
        }

        private void readFile(String tableName, List<Long> lines){
            while (lines.size() > 0)
            {
                Long lineNumber = lines.get(0);
                lines.remove(lineNumber);
                long startLine = lineNumber; // 起始行号
//                System.out.println(startLine);
                long endLine = startLine + 500; // 终止行号

                List<String> liness = new ArrayList<>();

                try (BufferedReader reader = new BufferedReader(new FileReader(this.totalPath))) {
                    String line;
                    int currentLine = 0;

                    while ((line = reader.readLine()) != null) {
                        currentLine++;

                        if (currentLine >= startLine && currentLine <= endLine) {
                            liness.add(line);
                        }

                        if (currentLine == endLine) {
                            Thread t = new Thread(new AsyncFileWrite(liness, tableName));
                            t.start();
                            threadList.add(t);
                            break; // 如果已经达到终止行，退出循环

                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            for (Thread t : threadList) {
                try {
                    t.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void run() {
            readFile(tableName, lines);
        }


    }

}
